/*
 * Copyright (C) 2015 The Sven Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cc.core.util;

import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader.TileMode;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;

@SuppressWarnings("unused")
public class BitmapUtil {

    public static android.graphics.Bitmap openBitmapFromPath(String path) {
        try {

            FileInputStream stream = new FileInputStream(path);

            return BitmapFactory.decodeStream(stream);

        } catch (Exception e) {
            //e.printStackTrace();
        }
        return null;
    }

    public static byte[] BitmapToBytes(android.graphics.Bitmap bitmap, int quality) {

        ByteArrayOutputStream bAOS = new ByteArrayOutputStream();

        bitmap.compress(android.graphics.Bitmap.CompressFormat.PNG, quality, bAOS);

        return bAOS.toByteArray();
    }

    public static android.graphics.Bitmap BytesToBitmap(byte[] bytes) {

        if (bytes.length != 0)
            return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);

        else
            return null;
    }

    public static android.graphics.Bitmap drawableToBitmap(Drawable drawable) {
        int w = drawable.getIntrinsicWidth();
        int h = drawable.getIntrinsicHeight();

        Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Config.ARGB_8888
                : Config.RGB_565;

        android.graphics.Bitmap bitmap = android.graphics.Bitmap.createBitmap(w, h, config);

        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, w, h);

        drawable.draw(canvas);

        return bitmap;
    }

    public static android.graphics.Bitmap getRoundedCornerBitmap(android.graphics.Bitmap bitmap, float roundPx) {

        int w = bitmap.getWidth();
        int h = bitmap.getHeight();

        android.graphics.Bitmap output = android.graphics.Bitmap.createBitmap(w, h, Config.ARGB_8888);

        Canvas canvas = new Canvas(output);

        final int color = 0xff424242;
        final Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, w, h);
        final RectF rectF = new RectF(rect);

        paint.setAntiAlias(true);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(color);

        canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
        paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rect, paint);

        return output;
    }


    public static android.graphics.Bitmap createReflectionImageWithOrigin(android.graphics.Bitmap bitmap) {

        final int reflectionGap = 4;
        int w = bitmap.getWidth();
        int h = bitmap.getHeight();

        Matrix matrix = new Matrix();
        matrix.preScale(1, -1);

        android.graphics.Bitmap reflectionImage = android.graphics.Bitmap.createBitmap(bitmap, 0, h / 2, w, h / 2, matrix, false);

        android.graphics.Bitmap bitmapWithReflection = android.graphics.Bitmap.createBitmap(w, (h + h / 2), Config.ARGB_8888);

        Canvas canvas = new Canvas(bitmapWithReflection);
        canvas.drawBitmap(bitmap, 0, 0, null);
        Paint defaultPaint = new Paint();
        canvas.drawRect(0, h, w, h + reflectionGap, defaultPaint);

        canvas.drawBitmap(reflectionImage, 0, h + reflectionGap, null);

        Paint paint = new Paint();
        LinearGradient shader = new LinearGradient(0, bitmap.getHeight(), 0,
                bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff, 0x00ffffff, TileMode.CLAMP);
        paint.setShader(shader);
        paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));

        canvas.drawRect(0, h, w, bitmapWithReflection.getHeight() + reflectionGap, paint);

        return bitmapWithReflection;
    }

    @SuppressWarnings("deprecation")
    public static Drawable zoomDrawable(Drawable drawable, int w, int h) {

        int width = drawable.getIntrinsicWidth();
        int height = drawable.getIntrinsicHeight();

        android.graphics.Bitmap oldBmp = drawableToBitmap(drawable);

        Matrix matrix = new Matrix();

        float sx = ((float) w / width);
        float sy = ((float) h / height);

        matrix.postScale(sx, sy);

        android.graphics.Bitmap newBmp = android.graphics.Bitmap.createBitmap(oldBmp, 0, 0, width, height, matrix, true);
        return new BitmapDrawable(newBmp);
    }

    public static android.graphics.Bitmap zoomBitmap(android.graphics.Bitmap bitmap, int width, int height) {

        int w = bitmap.getWidth();
        int h = bitmap.getHeight();

        Matrix matrix = new Matrix();

        float scaleWidth = ((float) width / w);
        float scaleHeight = ((float) height / h);

        matrix.postScale(scaleWidth, scaleHeight);

        return android.graphics.Bitmap.createBitmap(bitmap, 0, 0, w, h, matrix, true);
    }


    public static android.graphics.Bitmap blurImageAmeliorate(android.graphics.Bitmap bmp) {
        long start = System.currentTimeMillis();

        int[] gauss = new int[]{1, 2, 1, 2, 4, 2, 1, 2, 1};

        int width = bmp.getWidth();
        int height = bmp.getHeight();
        android.graphics.Bitmap bitmap = android.graphics.Bitmap.createBitmap(width, height, Config.RGB_565);

        int pixR;
        int pixG;
        int pixB;

        int pixColor;

        int newR = 0;
        int newG = 0;
        int newB = 0;

        int delta = 16;

        int idx;
        int[] pixels = new int[width * height];
        bmp.getPixels(pixels, 0, width, 0, 0, width, height);
        for (int i = 1, length = height - 1; i < length; i++) {
            for (int k = 1, len = width - 1; k < len; k++) {
                idx = 0;
                for (int m = -1; m <= 1; m++) {
                    for (int n = -1; n <= 1; n++) {
                        pixColor = pixels[(i + m) * width + k + n];

                        pixR = Color.red(pixColor);
                        pixG = Color.green(pixColor);
                        pixB = Color.blue(pixColor);

                        newR = newR + (pixR * gauss[idx]);
                        newG = newG + (pixG * gauss[idx]);
                        newB = newB + (pixB * gauss[idx]);
                        idx++;
                    }
                }

                newR /= delta;
                newG /= delta;
                newB /= delta;

                newR = Math.min(255, Math.max(0, newR));
                newG = Math.min(255, Math.max(0, newG));
                newB = Math.min(255, Math.max(0, newB));

                pixels[i * width + k] = Color.argb(255, newR, newG, newB);

                newR = 0;
                newG = 0;
                newB = 0;
            }
        }

        bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
        //long end = System.currentTimeMillis();
        return bitmap;
    }

}
